﻿using System;
using System.Collections.Generic;
using System.IO;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Profile;
using Aliyun.Acs.Sts.Model.V20150401;
using Aliyun.OSS;

namespace Pay.Core {
	public class AliyunOSS {
		public AliyunOSS(string key, string secret, string endpoint) {
			_log = IocHelper.Get<ILogHelper>("ui_error");
			if (string.IsNullOrEmpty(endpoint))
				endpoint = _endpoint;
			_client = new OssClient(endpoint, key, secret);
		}
		/// <summary>
		/// OSS的访问地址
		/// </summary>
		private string _endpoint = "oss-cn-shenzhen.aliyuncs.com";
		/// <summary>
		/// 存储空间名称
		/// </summary>
		//private string _bucketName = "bucket-sfb";

		private ILogHelper _log;

		private OssClient _client;

		/// <summary>
		/// 创建一个新的存储空间
		/// </summary>
		public bool CreateBucket(string bucketName) {
			try {
				var result = _client.CreateBucket(bucketName);
				return true;
			} catch (Exception ex) {
				_log.Info(string.Format("创建存储空间失败. 原因： {0}", ex.Message));
				return false;
			}
		}

		/// <summary>
		/// 上传指定的文件到指定的OSS的存储空间
		/// </summary>
		/// <param name="bucketName">指定的存储空间名称</param>
		/// <param name="key">文件的在OSS上保存的名称</param>
		/// <param name="fileToUpload">指定上传文件的本地路径</param>
		public bool PutObject(string bucketName, string key, string fileToUpload) {
			try {
				var result = _client.PutObject(bucketName, key, fileToUpload);
				return true;
			} catch (Exception ex) {
				_log.Info(string.Format("Put object failed, {0}", ex.Message));
				return false;
			}
		}

		/// <summary>
		/// 上传指定的文件流到指定的OSS的存储空间
		/// </summary>
		/// <param name="bucketName">指定的存储空间名称</param>
		/// <param name="key">文件的在OSS上保存的名称</param>
		/// <param name="fileToUpload">文件流</param>
		public bool PutObject(string bucketName, string key, Stream fileToUpload) {
			try {
				var result = _client.PutObject(bucketName, key, fileToUpload);
				return true;
			} catch (Exception ex) {
				_log.Info(string.Format("Put object failed, {0}", ex.Message));
				return false;
			}
		}

		/// <summary>
		/// 列出指定存储空间的文件列表
		/// </summary>
		/// <param name="bucketName">存储空间的名称</param>
		/// <param name="folder">文件夹：如goods/{merchant_no}/</param>
		public List<oss_bucket_file> ListObjects(string bucketName, string folder) {
			List<oss_bucket_file> list = new List<oss_bucket_file>();
			try {
				ObjectListing result = null;
				string nextMarker = string.Empty;
				do {
					var listObjectsRequest = new ListObjectsRequest(bucketName) {
						Prefix = folder,
						Delimiter = "/"
					};
					result = _client.ListObjects(listObjectsRequest);
					foreach (var summary in result.ObjectSummaries) {
						list.Add(new oss_bucket_file { name = summary.Key, size = summary.Size });
					}
					nextMarker = result.NextMarker;
				} while (result.IsTruncated);
			} catch (Exception ex) {
				_log.Info(string.Format("List object failed, {0}", ex.Message));
			}
			return list;
		}

		/// <summary>
		/// 从指定的OSS存储空间中获取指定的文件
		/// </summary>
		/// <param name="bucketName">要获取的文件所在的存储空间名称</param>
		/// <param name="key">要获取的文件在OSS上的名称</param>
		/// <param name="fileToDownload">本地存储下载文件的目录<param>
		public bool GetObject(string bucketName, string key, string fileToDownload) {
			try {
				var obj = _client.GetObject(bucketName, key);

				//将从OSS读取到的文件写到本地
				using (var requestStream = obj.Content) {
					byte[] buf = new byte[1024];
					using (var fs = File.Open(fileToDownload, FileMode.OpenOrCreate)) {
						var len = 0;
						while ((len = requestStream.Read(buf, 0, 1024)) != 0) {
							fs.Write(buf, 0, len);
						}
					}
				}
				return true;
			} catch (Exception ex) {
				_log.Info(string.Format("Get object failed, {0}", ex.Message));
				return false;
			}
		}

		/// <summary>
		/// 删除指定的文件
		/// </summary>   
		/// <param name="bucketName">文件所在存储空间的名称</param>
		/// <param name="key">待删除的文件名称</param>
		public bool DeleteObject(string bucketName, string key) {
			try {
				_client.DeleteObject(bucketName, key);
				return true;
			} catch (Exception ex) {
				_log.Info(string.Format("Delete object failed, {0}", ex.Message));
				return false;
			}
		}
	}

	/// <summary>
	/// 授权返回值
	/// </summary>
	public class OSSToken {
		/// <summary>
		/// STS是Global Service, API入口位于华东 1 (杭州) , 这里Region填写"cn-hangzhou"
		/// 只有 RAM用户（子账号）才能调用 AssumeRole 接口
		/// 阿里云主账号的AccessKeys不能用于发起AssumeRole请求
		/// 请首先在RAM控制台创建一个RAM用户，并为这个用户创建AccessKeys
		/// RoleArn 需要在 RAM 控制台上获取
		/// RoleSessionName 是临时Token的会话名称，自己指定用于标识你的用户，主要用于审计，或者用于区分Token颁发给谁
		/// 但是注意RoleSessionName的长度和规则，不要有空格，只能有'-' '_' 字母和数字等字符
		/// 具体规则请参考API文档中的格式要求
		/// </summary>
		/// <returns>The oken.</returns>
		public oss_sts_token STSToken(string key = "", string secret = "", string arn = "1366398190353749") {
			// 构建一个 Aliyun Client, 用于发起请求
			// 构建Aliyun Client时需要设置AccessKeyId和AccessKeySevcret
			// STS是Global Service, API入口位于华东 1 (杭州) , 这里Region填写"cn-hangzhou"
			string region = "cn-shenzhen";
			IClientProfile profile = DefaultProfile.GetProfile(region, key, secret);
			DefaultAcsClient client = new DefaultAcsClient(profile);

			// 构造AssumeRole请求
			AssumeRoleRequest request = new AssumeRoleRequest();
			// 指定角色Arn
			//request.RoleArn = string.Format("acs:ram::{0}:role/aliyunosstokengeneratorrole", arn);
			//request.RoleSessionName = "AliyunOSSTokenGeneratorRole";
			request.RoleArn = string.Format("acs:ram::{0}:role/aliyunosstokengeneratorrole", arn);
			request.RoleSessionName = "AliyunOSSTokenGeneratorUserPolicy";

			// 可以设置Token有效期，可选参数，默认3600秒；
			// request.DurationSeconds = 3600;
			// 可以设置Token的附加Policy，可以在获取Token时，通过额外设置一个Policy进一步减小Token的权限；
			// request.Policy="<policy-content>"

			try {
				AssumeRoleResponse response = client.GetAcsResponse(request);
				//Token过期时间；服务器返回UTC时间，这里转换成北京时间显示；
				return new oss_sts_token {
					accesskey_id = response.Credentials.AccessKeyId, accesskey_secret = response.Credentials.AccessKeySecret,
					token = response.Credentials.SecurityToken, expiration = DateTime.Parse(response.Credentials.Expiration).ToLocalTime()
				};
			} catch (Exception ex) {
				var _log = IocHelper.Get<ILogHelper>("ui_error");
				_log.Info(string.Format("token object failed, {0}", ex.Message));
				return null;
			}
		}
	}

	/// <summary>
	/// 授权返回值
	/// </summary>
	public class oss_sts_token {
		/// <summary>
		/// OSS的访问ID
		/// </summary>
		public string accesskey_id { get; set; }
		/// <summary>
		/// OSS的访问密钥
		/// </summary>
		public string accesskey_secret { get; set; }
		/// <summary>
		/// 授权token
		/// </summary>
		public string token { get; set; }
		/// <summary>
		/// 过期时间
		/// </summary>
		public DateTime expiration { get; set; }
	}

	/// <summary>
	/// 指定存储空间的文件列表
	/// </summary>
	public class oss_bucket_file {
		/// <summary>
		/// 文件名
		/// </summary>
		/// <value>The key.</value>
		public string name { get; set; }
		public long size { get; set; }
	}
}
